home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / macabuse / imlib / timage.c < prev    next >
C/C++ Source or Header  |  1997-05-20  |  27KB  |  1,023 lines

  1. #include "timage.hpp"
  2. #include "dprint.hpp"
  3.  
  4. void trans_image::make_color(int c)
  5. {
  6.   unsigned char *dp=data;
  7.   int y,x;
  8.   for (y=0;y<h;y++)
  9.   {
  10.     x=0;
  11.     while(x<w)
  12.     {
  13.       x+=*(dp++);
  14.       if (x<w)
  15.       {     
  16.                 int run=*(dp++);
  17.                 memset(dp,c,run);
  18.                 x+=run;
  19.                 dp+=run;
  20.       }
  21.     }
  22.   }
  23. }
  24.  
  25. image *trans_image::make_image()
  26. {
  27.   image *im=new image(w,h);
  28.   unsigned char *d=im->scan_line(0),*dp=data,*dline;
  29.   int y,x;
  30.   for (y=0;y<h;y++)
  31.   {
  32.     x=0;
  33.     dline=d;
  34.     memset(dline,0,w);
  35.     while(x<w)
  36.     {
  37.       int skip=*(dp++);
  38.       dline+=skip;
  39.       x+=skip;
  40.       if (x<w)
  41.       {     
  42.                 int run=*(dp++);
  43.                 memcpy(dline,dp,run);
  44.                 x+=run;
  45.                 dline+=run;
  46.                 dp+=run;
  47.       }
  48.     }
  49.     d=im->next_line(y,d);
  50.   }
  51.   return im;
  52. }
  53.  
  54. trans_image::trans_image(image *im, char *name)
  55. {
  56.   int size=0,x,y;
  57.   unsigned char *sl,*datap,*marker; 
  58.   w=im->width();
  59.   h=im->height();
  60.   
  61.   // first we must find out how much data to allocate
  62.   for (y=0;y<im->height();y++)
  63.   {
  64.     sl=im->scan_line(y);
  65.     x=0;    
  66.     while (x<w)
  67.     {      
  68.       size++;     
  69.       while (x<w && *sl==0) { sl++; x++; }      
  70.                                  
  71.       if (x<w)
  72.       {
  73.         size++;  // byte for the size of the run    
  74.         while (x<w && (*sl)!=0)
  75.         {
  76.                   size++;
  77.                   x++;
  78.                   sl++;      
  79.                 }    
  80.       }
  81.     }        
  82.   }  
  83.  
  84. #ifdef MEM_CHECK
  85.   char st[80];
  86.   sprintf(st,"trans_image::data (%s)",name);
  87.   data=(unsigned char *)jmalloc(size,st);
  88. #else
  89.   data=(unsigned char *)jmalloc(size,"");
  90. #endif
  91.   int ww=im->width(),hh=im->height();
  92.   datap=data;
  93.   if (!datap)
  94.   { dprintf("size = %d %d (%d)\n",im->width(),im->height(),size);  }
  95.   CONDITION(datap,"malloc error for trans_image::data");
  96.   
  97.   for (y=0;y<hh;y++)  // now actually make the runs
  98.   {
  99.     sl=im->scan_line(y);
  100.     x=0;    
  101.     while (x<ww)
  102.     {      
  103.       *datap=0;  // start the skip at 0       
  104.       while (x<im->width() && (*sl)==0) 
  105.       { sl++; x++; (*datap)++; }      
  106.       datap++;      
  107.                                  
  108.       if (x<ww)
  109.       {
  110.         marker=datap;   // let marker be the run size
  111.                 *marker=0;
  112.                 datap++;    // skip over this spot        
  113.         while (x<im->width() && (*sl)!=0)
  114.         {    
  115.           (*marker)++;      
  116.                       (*datap)=*sl;
  117.           datap++;      
  118.                   x++;
  119.                   sl++;            
  120.                 }    
  121.       }
  122.     }        
  123.   }  
  124. }
  125.  
  126. void trans_image::put_scan_line(image *screen, int x, int y, int line)   // always transparent   
  127. {
  128.   short x1,y1,x2,y2;
  129.   screen->get_clip(x1,y1,x2,y2);
  130.   if (y+line<y1 || y+line>y2 || x>x2 || x+w-1<x1)            // clipped off completely?
  131.     return;
  132.  
  133.   unsigned char *datap=data;
  134.   int ix;  
  135.   while (line)            // skip scan line data until we get to the line of interest
  136.   {
  137.     for (ix=0;ix<w;)      
  138.     {      
  139.       ix+=*datap;        // skip blank space
  140.       datap++;
  141.       if (ix<w)          
  142.       {    
  143.                 int run_length=*datap;     // skip run
  144.                 ix+=run_length;
  145.                 datap+=run_length+1;
  146.       }      
  147.     }
  148.     line--;    
  149.     y++;    
  150.   }
  151.   
  152.   
  153.   // now slam this list of runs to the screen
  154.   unsigned char *screen_line=screen->scan_line(y)+x;
  155.     
  156.   for (ix=0;ix<w;)             
  157.   {      
  158.     int skip=*datap;              // how much space to skip?
  159.     datap++;
  160.     screen_line+=skip;
  161.     ix+=skip;    
  162.     
  163.     if (ix<w)
  164.     {      
  165.       int run_length=*datap;
  166.       datap++;
  167.  
  168.       if (x+ix+run_length-1<x1)      // is this run clipped out totally?
  169.       {
  170.                 datap+=run_length;
  171.                 ix+=run_length;
  172.                 screen_line+=run_length;
  173.       }
  174.       else
  175.       {     
  176.                 if (x+ix<x1)                 // is the run clipped partially?
  177.                 {    
  178.                   int clip=(x1-(x+ix));    
  179.                   datap+=clip;    
  180.                   run_length-=clip;
  181.                   screen_line+=clip;
  182.                   ix+=clip;    
  183.                 }
  184.             
  185.                 if (x+ix>x2)                      // clipped totally on the right?  
  186.           return ;                        // we are done, return!
  187.                 else if (x+ix+run_length-1>x2)    // partially clipped?
  188.                 {
  189.                   memcpy(screen_line,datap,(x+ix+run_length-1)-x2);   // slam what we can
  190.                   return ;    // and return 'cause we are done with the line
  191.         } else
  192.         {
  193.                   memcpy(screen_line,datap,run_length);    
  194.                   screen_line+=run_length;
  195.                 datap+=run_length;
  196.                 ix+=run_length;            
  197.         }      
  198.       }    
  199.     }
  200.   }
  201.  
  202. }
  203.  
  204.  
  205. inline unsigned char *trans_image::clip_y(image *screen, int x1, int y1, int x2, int y2, 
  206.                    int x, int &y, int &ysteps)
  207. {
  208.   // check to see if it is total clipped out first
  209.   if (y+h<=y1 || y>y2 || x>x2 || x+w<=x1)
  210.     return NULL;
  211.  
  212.   register unsigned char *datap=data;  
  213.  
  214.  
  215.   ysteps=height();
  216.   
  217.   if (y<y1)  // check to see if the image gets clipped at the top
  218.   {
  219.  
  220.  
  221.     // because data is stored in runs, we need to skip over the top clipped portion
  222.     int skips=(y1-y);     // how many lines do we need to skip?    
  223.     ysteps-=skips;        // reduce h (number of lines to draw)
  224.     y=y1;                // start drawing here now
  225.     while (skips--)
  226.     {      
  227.       register int ix=0;
  228.       while (ix<w)
  229.       {    
  230.         ix+=(*datap);       // skip over empty space
  231.         datap++; 
  232.         if (ix<w)              
  233.         { ix+=*datap;         
  234.         datap+=(*datap)+1;   // skip over data
  235.         }    
  236.       }      
  237.     }
  238.   }
  239.   
  240.   if (y+ysteps>y2)  // check to see if it gets clipped at the bottom
  241.     ysteps-=(y+ysteps-y2-1);
  242.  
  243.   screen->add_dirty(max(x,x1),y,min(x+width()-1,x2),y+h-1);  
  244.   return datap;
  245.  
  246. void trans_image::put_image_filled(image *screen, int x, int y, 
  247.                    uchar fill_color)
  248. {
  249.  short x1,y1,x2,y2;
  250.   int slam_length,chop_length,ysteps;
  251.  
  252.   screen->get_clip(x1,y1,x2,y2);
  253.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  254.   if (!datap) return ;     // if clip_y says nothing to draw, return
  255.   
  256.   screen_line=screen->scan_line(y)+x;  
  257.   int sw=screen->width()-w;
  258.   x1-=x; x2-=x;
  259.   for (;ysteps>0;ysteps--)
  260.   {         
  261.     register int ix,slam_length;
  262.     for (ix=0;ix<w;)
  263.     {
  264.       int blank=(*datap);
  265.       memset(screen_line,fill_color,blank);
  266.       ix+=blank;       // skip over empty space
  267.       screen_line+=blank;
  268.       
  269.       datap++; 
  270.       if (ix<w)              
  271.       { 
  272.                 slam_length=*datap;     // find the length of this run      
  273.                 datap++;      
  274.                 if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  275.                 {
  276.                   datap+=slam_length;
  277.                   ix+=slam_length;
  278.                   screen_line+=slam_length;
  279.                 }
  280.                 else
  281.                 {                
  282.                   if (ix<x1)                // the left side needs to be chopped ?
  283.                   {                  
  284.                     chop_length=(x1-ix); 
  285.                     
  286.                     if (chop_length>=slam_length)  // see if we chopped it all off
  287.                     {                              // yes, we did
  288.                       ix+=slam_length;             // advance everything to the end of run
  289.                       screen_line+=slam_length;
  290.                       datap+=slam_length;          
  291.                       slam_length=0;           
  292.                     } else
  293.                     {         
  294.                       slam_length-=chop_length;   // else advance everything to begining of slam  
  295.                       ix+=chop_length;
  296.                       screen_line+=chop_length;
  297.                       datap+=chop_length;        
  298.                     }        
  299.                   }            
  300.             
  301.                   if (slam_length)   // see if there is anything left to slam
  302.                   {
  303.                     if (ix+slam_length>x2) // see if right side needs to be chopped off
  304.                       memcpy(screen_line,datap,x2-ix+1);
  305.                     else
  306.                       memcpy(screen_line,datap,slam_length);
  307.                     datap+=slam_length;
  308.                     ix+=slam_length;        
  309.                     screen_line+=slam_length;
  310.                   }                   
  311.                 }
  312.       }      
  313.     }
  314.     screen_line+=sw;
  315.   }    
  316. }
  317.  
  318. void trans_image::put_image_offseted(image *screen, uchar *s_off)   // if screen x & y offset already calculated save a mul
  319. {
  320.   int ix,ysteps=height();
  321.   int screen_skip=screen->width()-w;
  322.   uchar skip,*datap=data;
  323.   for (;ysteps;ysteps--)
  324.   {
  325.     for (ix=0;ix<w;)
  326.     {
  327.       skip=*datap;       // skip leading blank space
  328.       datap++;
  329.       ix+=skip;
  330.       s_off+=skip;
  331.  
  332.       if (s_off<screen->scan_line(0))
  333.           dprintf("bad write");
  334.  
  335.  
  336.       if (ix<w)
  337.       {
  338.     skip=*datap;
  339.     datap++;
  340.     memcpy(s_off,datap,skip);
  341.     datap+=skip;
  342.     s_off+=skip;
  343.     ix+=skip;
  344.  
  345.     if (s_off>=screen->scan_line(screen->height()+1))
  346.             dprintf("bad write");
  347.       }
  348.     }
  349.     s_off+=screen_skip;
  350.   }
  351. }
  352.  
  353. void trans_image::put_image(image *screen, int x, int y) 
  354. {
  355.   short x1,y1,x2,y2;
  356.   int slam_length,chop_length,ysteps;
  357.  
  358.   screen->get_clip(x1,y1,x2,y2);
  359.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  360.   if (!datap) return ;     // if clip_y says nothing to draw, return
  361.   
  362.   screen_line=screen->scan_line(y)+x;  
  363.   int sw=screen->width();
  364.   x1-=x; x2-=x;
  365.   for (;ysteps>0;ysteps--)
  366.   {         
  367.     int ix,slam_length;
  368.     for (ix=0;ix<w;)
  369.     {
  370.       ix+=(*datap);       // skip over empty space
  371.       datap++; 
  372.       if (ix<w)              
  373.       { 
  374.                 slam_length=*datap;     // find the length of this run      
  375.                 datap++;      
  376.                 if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  377.                 {
  378.                   datap+=slam_length;
  379.                   ix+=slam_length;        
  380.                 }
  381.                 else
  382.                 {                
  383.                   if (ix<x1)                // the left side needs to be chopped ?
  384.                   {                  
  385.                     chop_length=(x1-ix); 
  386.                     
  387.                     if (chop_length>=slam_length)  // see if we chopped it all off
  388.                     {                              // yes, we did
  389.                       ix+=slam_length;             // advance everything to the end of run
  390.                       datap+=slam_length;          
  391.                       slam_length=0;           
  392.                     } else
  393.                     {         
  394.                       slam_length-=chop_length;   // else advance everything to begining of slam  
  395.                       ix+=chop_length;
  396.                       datap+=chop_length;        
  397.                     }        
  398.                   }            
  399.             
  400.                   if (slam_length)   // see if there is anything left to slam
  401.                   {
  402.                     if (ix+slam_length>x2) // see if right side needs to be chopped off
  403.                       memcpy(screen_line+ix,datap,x2-ix+1);
  404.                     else
  405.                       memcpy(screen_line+ix,datap,slam_length);
  406.                     datap+=slam_length;
  407.                     ix+=slam_length;        
  408.                   }                   
  409.                 }
  410.       }      
  411.     }
  412.     screen_line+=sw;
  413.   }    
  414. }
  415.  
  416. void trans_image::put_remaped(image *screen, int x, int y, unsigned char *remap) 
  417. {
  418.   short x1,y1,x2,y2;
  419.   int slam_length,chop_length,ysteps;
  420.  
  421.   screen->get_clip(x1,y1,x2,y2);
  422.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  423.   if (!datap) return ;     // if clip_y says nothing to draw, return
  424.   
  425.   screen_line=screen->scan_line(y)+x;  
  426.   int sw=screen->width();
  427.   x1-=x; x2-=x;
  428.   for (;ysteps>0;ysteps--)
  429.   {         
  430.     register int ix,slam_length;
  431.     for (ix=0;ix<w;)
  432.     {
  433.       ix+=(*datap);       // skip over empty space
  434.       datap++; 
  435.       if (ix<w)              
  436.       { 
  437.     slam_length=*datap;     // find the length of this run      
  438.     datap++;      
  439.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  440.     {
  441.       datap+=slam_length;
  442.       ix+=slam_length;        
  443.     }
  444.     else
  445.     {                
  446.       if (ix<x1)                // the left side needs to be chopped ?
  447.       {                  
  448.         chop_length=(x1-ix); 
  449.         
  450.         if (chop_length>=slam_length)  // see if we chopped it all off
  451.         {                              // yes, we did
  452.           ix+=slam_length;             // advance everything to the end of run
  453.           datap+=slam_length;          
  454.           slam_length=0;           
  455.         } else
  456.         {         
  457.           slam_length-=chop_length;   // else advance everything to begining of slam  
  458.           ix+=chop_length;
  459.           datap+=chop_length;        
  460.         }        
  461.       }            
  462.  
  463.  
  464.       if (slam_length)   // see if there is anything left to slam
  465.       {
  466.         register int counter;
  467.         if (ix+slam_length>x2) // see if right side needs to be chopped off        
  468.           counter=x2-ix+1;
  469.         else
  470.           counter=slam_length;
  471.  
  472.         register unsigned char *sl=screen_line+ix,*sl2=datap;
  473.         ix+=slam_length;        
  474.         datap+=slam_length;
  475.         while (counter)
  476.         {
  477.           counter--;
  478.           *(sl)=remap[*(sl2)];
  479.           sl++;
  480.           sl2++;
  481.         }
  482.       }                   
  483.     }
  484.       }      
  485.     }
  486.     screen_line+=sw;
  487.   }    
  488. }
  489.  
  490.  
  491.  
  492. void trans_image::put_double_remaped(image *screen, int x, int y, unsigned char *remap, unsigned char *remap2) 
  493. {
  494.   short x1,y1,x2,y2;
  495.   int slam_length,chop_length,ysteps;
  496.  
  497.   screen->get_clip(x1,y1,x2,y2);
  498.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  499.   if (!datap) return ;     // if clip_y says nothing to draw, return
  500.   
  501.   screen_line=screen->scan_line(y)+x;  
  502.   int sw=screen->width();
  503.   x1-=x; x2-=x;
  504.   for (;ysteps>0;ysteps--)
  505.   {         
  506.     register int ix,slam_length;
  507.     for (ix=0;ix<w;)
  508.     {
  509.       ix+=(*datap);       // skip over empty space
  510.       datap++; 
  511.       if (ix<w)              
  512.       { 
  513.     slam_length=*datap;     // find the length of this run      
  514.     datap++;      
  515.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  516.     {
  517.       datap+=slam_length;
  518.       ix+=slam_length;        
  519.     }
  520.     else
  521.     {                
  522.       if (ix<x1)                // the left side needs to be chopped ?
  523.       {                  
  524.         chop_length=(x1-ix); 
  525.         
  526.         if (chop_length>=slam_length)  // see if we chopped it all off
  527.         {                              // yes, we did
  528.           ix+=slam_length;             // advance everything to the end of run
  529.           datap+=slam_length;          
  530.           slam_length=0;           
  531.         } else
  532.         {         
  533.           slam_length-=chop_length;   // else advance everything to begining of slam  
  534.           ix+=chop_length;
  535.           datap+=chop_length;        
  536.         }        
  537.       }            
  538.  
  539.  
  540.       if (slam_length)   // see if there is anything left to slam
  541.       {
  542.         register int counter;
  543.         if (ix+slam_length>x2) // see if right side needs to be chopped off        
  544.           counter=x2-ix+1;
  545.         else
  546.           counter=slam_length;
  547.  
  548.         register unsigned char *sl=screen_line+ix,*sl2=datap;
  549.         ix+=slam_length;        
  550.         datap+=slam_length;
  551.         while (counter)
  552.         {
  553.           counter--;
  554.           *(sl)=remap2[remap[*(sl2)]];
  555.           sl++;
  556.           sl2++;
  557.         }
  558.       }                   
  559.     }
  560.       }      
  561.     }
  562.     screen_line+=sw;
  563.   }    
  564. }
  565.  
  566.  
  567.  
  568. void trans_image::put_fade(image *screen, int x, int y,
  569.                int frame_on, int total_frames, 
  570.                color_filter *f, palette *pal) 
  571. {
  572.   short x1,y1,x2,y2;
  573.   int ix,slam_length,chop_length,ysteps;
  574.  
  575.   screen->get_clip(x1,y1,x2,y2);
  576.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  577.                 *screen_line;
  578.   if (!datap) return ;
  579.  
  580.   unsigned char *screen_run,*paddr=(unsigned char *)pal->addr(),
  581.                 *caddr1,*caddr2,r_dest,g_dest,b_dest;
  582.  
  583.   long fixmul=(frame_on<<16)/total_frames;
  584.   for (;ysteps>0;ysteps--,y++)
  585.   {         
  586.     screen_line=screen->scan_line(y);
  587.       
  588.     for (ix=0;ix<w;)
  589.     {
  590.       ix+=(*datap);       // skip over empty space
  591.       datap++; 
  592.       if (ix<w)              
  593.       { 
  594.     slam_length=*datap;     // find the length of this run      
  595.     datap++;      
  596.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  597.     {
  598.       datap+=slam_length;
  599.       ix+=slam_length;        
  600.     }
  601.     else
  602.     {                
  603.       if (x+ix<x1)                // the left side needs to be chopped ?
  604.       {                  
  605.         chop_length=(x1-x-ix); 
  606.         
  607.         if (chop_length>=slam_length)  // see if we chopped it all off
  608.         {                              // yes, we did
  609.           ix+=slam_length;             // advance everything to the end of run
  610.           datap+=slam_length;          
  611.           slam_length=0;           
  612.         } else
  613.         {         
  614.           slam_length-=chop_length;   // else advance everything to begining of slam  
  615.           ix+=chop_length;
  616.           datap+=chop_length;        
  617.         }        
  618.       }            
  619.  
  620.       if (slam_length)   // see if there is anything left to slam
  621.       {
  622.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  623.           chop_length=x2-x-ix;
  624.         else chop_length=slam_length;
  625.         screen_run=screen_line+x+ix;
  626.               
  627.         slam_length-=chop_length;
  628.         ix+=chop_length;
  629.           
  630.         while (chop_length--)
  631.         {
  632.           caddr1=paddr+(int)(*screen_run)*3;
  633.           caddr2=paddr+(int)(*datap)*3;
  634.           
  635.           r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  636.           caddr1++; caddr2++;
  637.  
  638.           g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  639.           caddr1++; caddr2++;
  640.  
  641.           b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  642.           *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
  643.  
  644.           screen_run++;
  645.           datap++;        
  646.         }
  647.         datap+=slam_length;
  648.         ix+=slam_length;        
  649.       }                   
  650.     }
  651.       }      
  652.     }      
  653.   }    
  654. }
  655.  
  656.  
  657.  
  658.  
  659. void trans_image::put_fade_tint(image *screen, int x, int y,
  660.                 int frame_on, int total_frames, 
  661.                 uchar *tint,
  662.                 color_filter *f, palette *pal) 
  663. {
  664.   short x1,y1,x2,y2;
  665.   int ix,slam_length,chop_length,ysteps;
  666.  
  667.   screen->get_clip(x1,y1,x2,y2);
  668.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  669.                 *screen_line;
  670.   if (!datap) return ;
  671.  
  672.   unsigned char *screen_run,*paddr=(unsigned char *)pal->addr(),
  673.                 *caddr1,*caddr2,r_dest,g_dest,b_dest;
  674.  
  675.   long fixmul=(frame_on<<16)/total_frames;
  676.   for (;ysteps>0;ysteps--,y++)
  677.   {         
  678.     screen_line=screen->scan_line(y);
  679.       
  680.     for (ix=0;ix<w;)
  681.     {
  682.       ix+=(*datap);       // skip over empty space
  683.       datap++; 
  684.       if (ix<w)              
  685.       { 
  686.     slam_length=*datap;     // find the length of this run      
  687.     datap++;      
  688.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  689.     {
  690.       datap+=slam_length;
  691.       ix+=slam_length;        
  692.     }
  693.     else
  694.     {                
  695.       if (x+ix<x1)                // the left side needs to be chopped ?
  696.       {                  
  697.         chop_length=(x1-x-ix); 
  698.         
  699.         if (chop_length>=slam_length)  // see if we chopped it all off
  700.         {                              // yes, we did
  701.           ix+=slam_length;             // advance everything to the end of run
  702.           datap+=slam_length;          
  703.           slam_length=0;           
  704.         } else
  705.         {         
  706.           slam_length-=chop_length;   // else advance everything to begining of slam  
  707.           ix+=chop_length;
  708.           datap+=chop_length;        
  709.         }        
  710.       }            
  711.  
  712.       if (slam_length)   // see if there is anything left to slam
  713.       {
  714.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  715.           chop_length=x2-x-ix;
  716.         else chop_length=slam_length;
  717.         screen_run=screen_line+x+ix;
  718.               
  719.         slam_length-=chop_length;
  720.         ix+=chop_length;
  721.           
  722.         while (chop_length--)
  723.         {
  724.           caddr1=paddr+(int)(*screen_run)*3;
  725.           caddr2=paddr+(int)(tint[*datap])*3;
  726.           
  727.           r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  728.           caddr1++; caddr2++;
  729.  
  730.           g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  731.           caddr1++; caddr2++;
  732.  
  733.           b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
  734.           *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
  735.  
  736.           screen_run++;
  737.           datap++;        
  738.         }
  739.         datap+=slam_length;
  740.         ix+=slam_length;        
  741.       }                   
  742.     }
  743.       }      
  744.     }      
  745.   }    
  746. }
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753. void trans_image::put_color(image *screen, int x, int y, int color) 
  754. {
  755.   short x1,y1,x2,y2;
  756.   int ix,slam_length,chop_length,ysteps;
  757.   
  758.   screen->get_clip(x1,y1,x2,y2);
  759.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  760.                 *screen_line;
  761.   if (!datap) return ;
  762.   
  763.   
  764.   for (;ysteps>0;ysteps--,y++)
  765.   {         
  766.     screen_line=screen->scan_line(y);
  767.       
  768.     for (ix=0;ix<w;)
  769.     {
  770.       ix+=(*datap);       // skip over empty space
  771.       datap++; 
  772.       if (ix<w)              
  773.       { 
  774.     slam_length=*datap;     // find the length of this run      
  775.     datap++;      
  776.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  777.     {
  778.       datap+=slam_length;
  779.       ix+=slam_length;        
  780.     }
  781.     else
  782.     {                
  783.       if (x+ix<x1)                // the left side needs to be chopped ?
  784.       {                  
  785.         chop_length=(x1-x-ix); 
  786.         
  787.         if (chop_length>=slam_length)  // see if we chopped it all off
  788.         {                              // yes, we did
  789.           ix+=slam_length;             // advance everything to the end of run
  790.           datap+=slam_length;          
  791.           slam_length=0;           
  792.         } else
  793.         {         
  794.           slam_length-=chop_length;   // else advance everything to begining of slam  
  795.           ix+=chop_length;
  796.           datap+=chop_length;        
  797.         }        
  798.       }            
  799.  
  800.       if (slam_length)   // see if there is anything left to slam
  801.       {
  802.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  803.           memset(screen_line+x+ix,color,x2-x-ix+1);
  804.         else
  805.           memset(screen_line+x+ix,color,slam_length);
  806.         datap+=slam_length;
  807.         ix+=slam_length;        
  808.       }    
  809.     }
  810.       }      
  811.     }      
  812.   }    
  813. }
  814.  
  815.  
  816. // ASSUMES that the blend image completly covers this image
  817. void trans_image::put_blend16(image *screen, image *blend, int x, int y, 
  818.                   int blendx, int blendy, int blend_amount, color_filter *f, palette *pal)
  819.  
  820. {
  821.   short x1,y1,x2,y2;
  822.   int ix,slam_length,chop_length,ysteps,rx1,rx2;
  823.   unsigned char *paddr=(unsigned char *)pal->addr();  
  824.   
  825.   screen->get_clip(x1,y1,x2,y2);
  826.   unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
  827.                 *blend_line,*screen_line;
  828.   if (!datap) return ;
  829.   CONDITION(y>=blendy && y+ysteps<blendy+blend->height()+1,"Blend doesn't fit on trans_image");
  830.   
  831.   blend_amount=16-blend_amount;
  832.   
  833.   for (;ysteps>0;ysteps--,y++)
  834.   {         
  835.     screen_line=screen->scan_line(y);
  836.     blend_line=blend->scan_line(y-blendy);
  837.     
  838.       
  839.     for (ix=0;ix<w;)
  840.     {
  841.       ix+=(*datap);       // skip over empty space
  842.       datap++; 
  843.       if (ix<w)              
  844.       { 
  845.     slam_length=*datap;     // find the length of this run      
  846.     datap++;      
  847.     if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
  848.     {
  849.       datap+=slam_length;
  850.       ix+=slam_length;        
  851.     }
  852.     else
  853.     {                
  854.       if (x+ix<x1)                // the left side needs to be chopped ?
  855.       {                  
  856.         chop_length=(x1-x-ix); 
  857.         
  858.         if (chop_length>=slam_length)  // see if we chopped it all off
  859.         {                              // yes, we did
  860.           ix+=slam_length;             // advance everything to the end of run
  861.           datap+=slam_length;          
  862.           slam_length=0;           
  863.         } else
  864.         {         
  865.           slam_length-=chop_length;   // else advance everything to begining of slam  
  866.           ix+=chop_length;
  867.           datap+=chop_length;        
  868.         }        
  869.       }            
  870.  
  871.       if (slam_length)   // see if there is anything left to slam
  872.       {
  873.  
  874.         if (x+ix+slam_length>x2) // see if right side needs to be chopped off
  875.           chop_length=x2-x-ix;
  876.         else chop_length=slam_length;
  877.  
  878.         unsigned char *screen_run=screen_line+x+ix,
  879.                       *blend_run=blend_line+x+ix-blendx,
  880.                       *caddr1,*caddr2,r_dest,g_dest,b_dest;      
  881.               
  882.         slam_length-=chop_length;
  883.         ix+=chop_length;    
  884.  
  885.  
  886.         while (chop_length--)
  887.         {
  888.           caddr1=paddr+(int)(*blend_run)*3;
  889.           caddr2=paddr+(int)(*datap)*3;
  890.           
  891.           r_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
  892.           caddr1++; caddr2++;
  893.  
  894.           g_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
  895.           caddr1++; caddr2++;
  896.  
  897.           b_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
  898.  
  899.           *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
  900.  
  901.           
  902.           screen_run++;
  903.           blend_run++;
  904.           datap++;        
  905.         }
  906.         datap+=slam_length;
  907.         ix+=slam_length;        
  908.       }                 
  909.  
  910.     }
  911.       }      
  912.     }      
  913.   }    
  914.  
  915.  
  916. }
  917.  
  918. void trans_image::put_predator(image *screen, int x, int y) 
  919. {
  920.   short x1,y1,x2,y2;
  921.   int slam_length,chop_length,ysteps;
  922.  
  923.   screen->get_clip(x1,y1,x2,y2);
  924.   register unsigned char *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
  925.   if (!datap) return ;     // if clip_y says nothing to draw, return
  926.  
  927.   // see if the last scanline is clipped off
  928.   if (y+ysteps==y2) ysteps-=2;
  929.   else if (y+ysteps==y2-1) ysteps--;
  930. /*  {
  931.     for (int x=0;x<w;)
  932.     {
  933.       int skip=*datap; datap++;
  934.       x+=skip;
  935.       if (x<w)
  936.       {
  937.     int run_size=*datap;
  938.     datap+=run_size+1;
  939.     x+=run_size;
  940.       }
  941.     }
  942.     if (y==y2) 
  943.       return;
  944.     else
  945.       y++;    
  946.   }*/
  947.   
  948.   screen_line=screen->scan_line(y)+x;  
  949.   int sw=screen->width();
  950.   x1-=x; x2-=x;
  951.   for (;ysteps>0;ysteps--)
  952.   {         
  953.     register int ix,slam_length;
  954.     for (ix=0;ix<w;)
  955.     {
  956.       ix+=(*datap);       // skip over empty space
  957.       datap++; 
  958.       if (ix<w)              
  959.       { 
  960.     slam_length=*datap;     // find the length of this run      
  961.     datap++;      
  962.     if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
  963.     {
  964.       datap+=slam_length;
  965.       ix+=slam_length;        
  966.     }
  967.     else
  968.     {                
  969.       if (ix<x1)                // the left side needs to be chopped ?
  970.       {                  
  971.         chop_length=(x1-ix); 
  972.         
  973.         if (chop_length>=slam_length)  // see if we chopped it all off
  974.         {                              // yes, we did
  975.           ix+=slam_length;             // advance everything to the end of run
  976.           datap+=slam_length;          
  977.           slam_length=0;           
  978.         } else
  979.         {         
  980.           slam_length-=chop_length;   // else advance everything to begining of slam  
  981.           ix+=chop_length;
  982.           datap+=chop_length;        
  983.         }        
  984.       }            
  985.  
  986.       if (slam_length)   // see if there is anything left to slam
  987.       {
  988.         if (ix+slam_length>x2) // see if right side needs to be chopped off
  989.           memcpy(screen_line+ix,screen_line+sw+sw+ix,x2-ix+1);
  990.         else
  991.           memcpy(screen_line+ix,screen_line+sw+sw+ix,slam_length);
  992.         datap+=slam_length;
  993.         ix+=slam_length;        
  994.       }                   
  995.     }
  996.       }      
  997.     }
  998.     screen_line+=sw;
  999.   }    
  1000. }
  1001.  
  1002. int trans_image::size()
  1003. {
  1004.   uchar *d=data;
  1005.   int t=0;
  1006.   for (int y=0;y<h;y++)
  1007.   {
  1008.     int x=0;
  1009.     while (x<w)
  1010.     {
  1011.       x+=*d; d++; t++;
  1012.       if (x<w)
  1013.       {
  1014.     int s=*d; d++; t+=s+1;
  1015.     d+=s;
  1016.     x+=s;
  1017.       }      
  1018.     }
  1019.   }
  1020.   return t+4+4;
  1021. }
  1022.